package com.heu.miaosha.service.impl;

import com.heu.miaosha.dao.ItemDOMapper;
import com.heu.miaosha.dao.ItemStockDOMapper;
import com.heu.miaosha.dao.StockLogDOMapper;
import com.heu.miaosha.dataobject.ItemDO;
import com.heu.miaosha.dataobject.ItemStockDO;
import com.heu.miaosha.dataobject.StockLogDO;
import com.heu.miaosha.error.BusinessException;
import com.heu.miaosha.error.EmBusinessError;
import com.heu.miaosha.mq.MqProducer;
import com.heu.miaosha.service.ItemService;
import com.heu.miaosha.service.PromoService;
import com.heu.miaosha.service.model.ItemModel;
import com.heu.miaosha.service.model.PromoModel;
import com.heu.miaosha.validator.ValidateImpl;
import com.heu.miaosha.validator.ValidationResult;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author: lidong
 * @description
 * @date: 2023/3/6 17:31
 */
@Service
public class ItemServiceImpl implements ItemService {


    @Autowired
    private ValidateImpl validator;

    @Autowired
    private ItemDOMapper itemDOMapper;

    @Autowired
    private ItemStockDOMapper itemStockDOMapper;


    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private PromoService promoService;

    @Autowired
    private StockLogDOMapper stockLogDOMapper;

    @Autowired
    private MqProducer mqProducer;



    private ItemDO convertItemDOFromItemModel(ItemModel itemModel){
        if (itemModel == null){
            return null;
        }
        ItemDO itemDO = new ItemDO();
        BeanUtils.copyProperties(itemModel,itemDO);
        itemDO.setPrice(itemModel.getPrice().doubleValue());
        return itemDO;
    }

    private ItemStockDO convertItemStockFromItemModel(ItemModel itemModel){
        if (itemModel == null){
            return null;
        }
        ItemStockDO itemStockDO = new ItemStockDO();
        itemStockDO.setItemId(itemModel.getId());
        itemStockDO.setStock(itemModel.getStock());

        return itemStockDO;
    }





    @Override
    @Transactional
    public ItemModel createItem(ItemModel itemModel) throws BusinessException {
        //校验入参
        ValidationResult result = validator.validate(itemModel);
        if(result.isHasErrors()){
            throw  new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR , result.getErrMsg());
        }
        //对象转化

        ItemDO itemDO = convertItemDOFromItemModel(itemModel);

        //写入数据库
        itemDOMapper.insertSelective(itemDO);
        itemModel.setId(itemDO.getId());

        ItemStockDO itemStockDO = this.convertItemStockFromItemModel(itemModel);
        itemStockDOMapper.insertSelective(itemStockDO);

        //返回对象
        return this.getItemById(itemModel.getId());
    }

    @Override
    public List<ItemModel> listItem() {
        List<ItemDO> itemDOList = itemDOMapper.listItem();
        List<ItemModel> itemModelList = itemDOList.stream().map(itemDO -> {
            ItemStockDO itemStockDO = itemStockDOMapper.selectByItemId(itemDO.getId());
            ItemModel itemModel = this.convertModelFromDataObject(itemDO, itemStockDO);
            return itemModel;
        }).collect(Collectors.toList());
        return itemModelList;
    }


    /**
     * 按照id查找商品信息
     * @param id
     * @return
     */
    @Override
    public ItemModel getItemById(Integer id) {
        ItemDO itemDO = itemDOMapper.selectByPrimaryKey(id);
        if (itemDO == null){
            return null;
        }
        ItemStockDO itemStockDO = itemStockDOMapper.selectByItemId(id);

        ItemModel itemModel = convertModelFromDataObject(itemDO, itemStockDO);

        //获取商品秒杀信息
        PromoModel promoModel = promoService.getPromoByItemId(itemModel.getId());
        if (promoModel != null && promoModel.getStatus().intValue() != 3){
            itemModel.setPromoModel(promoModel);
        }

        return itemModel;
    }
    private ItemModel convertModelFromDataObject(ItemDO itemDO, ItemStockDO itemStockDO){
        ItemModel itemModel = new ItemModel();
        BeanUtils.copyProperties(itemDO , itemModel);
        itemModel.setPrice(new BigDecimal(itemDO.getPrice()));
        itemModel.setStock(itemStockDO.getStock());
        return itemModel;
    }


    @Override
    public boolean asyncDecreaseStock(Integer itemID, Integer amount) {
        boolean mqResult = mqProducer.asyncReduceStock(itemID, amount);
        return  mqResult;
    }

    @Override
    public boolean increaseStock(Integer itemID, Integer amount) {
        redisTemplate.opsForValue().set("promo_item_stock_"+itemID , amount);
        return true;
    }


    @Override
    @Transactional
    public boolean decreaseStock(Integer itemID , Integer amount){
        long result = redisTemplate.opsForValue().increment("promo_item_stock_"+itemID,amount.intValue()*-1);


        if (result>0 ){
//            boolean mqResult = mqProducer.asyncReduceStock(itemID, amount);
//            if (!mqResult){
//                redisTemplate.opsForValue().increment("promo_item_stock_"+itemID , amount.intValue());
//                return false;
//            }
            return true;
        } else if (result == 0) {
            redisTemplate.opsForValue().set("promo_item_stock_invalid"+itemID , "true");
            return true;
        } else {
            redisTemplate.opsForValue().set("promo_item_stock_"+itemID , amount);
            return false;
        }
    }

    @Override
    @Transactional
    public void increseSales(Integer itemId, Integer amount) throws BusinessException {
        itemDOMapper.increaseSales(itemId,amount);
    }


    @Override
    @Transactional
    public String initStockLog(Integer itemId, Integer amount) {
        StockLogDO stockLogDO = new StockLogDO();
        stockLogDO.setItemId(itemId);
        stockLogDO.setAmount(amount);
        stockLogDO.setStockLogId(UUID.randomUUID().toString().replace("-",""));
        stockLogDO.setStatus(1);


        stockLogDOMapper.insertSelective(stockLogDO);
        return stockLogDO.getStockLogId();
    }

    @Override
    public ItemModel getItemByIdInCache(Integer id) {
        ItemModel itemModel = (ItemModel) redisTemplate.opsForValue().get("item_validate_"+id);
        if (itemModel == null){
            itemModel = this.getItemById(id);
            redisTemplate.opsForValue().set("item_validate_"+id , itemModel);
            redisTemplate.expire("user_validate_"+id,10, TimeUnit.MINUTES);
        }
        return itemModel;
    }




}
